/*
 * @copyright 2011 Gerald Jacobson
 * @license GNU General Public License
 * 
 * This file is part of GameTimer.
 *
 * GameTimer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * GameTimer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GameTimer. If not, see <http://www.gnu.org/licenses/>.
 */
package org.amphiption.gametimer.dao;

import java.util.ArrayList;
import java.util.List;

import org.amphiption.gametimer.entity.Entity.DbState;
import org.amphiption.gametimer.entity.Player;
import org.amphiption.gametimer.entity.TimerConfiguration;
import org.amphiption.gametimer.entity.TimerConfiguration.TimerType;

import android.content.Context;
import android.database.Cursor;

/**
 * This class is responsible of all database timer configuration access.
 * 
 * @author amphiprion
 * 
 */
public class TimerConfigurationDao extends AbstractDao {
	/** The singleton. */
	private static TimerConfigurationDao instance;

	/**
	 * Hidden constructor.
	 * 
	 * @param context
	 *            the application context
	 */
	private TimerConfigurationDao(Context context) {
		super(context);
	}

	/**
	 * Return the singleton.
	 * 
	 * @param context
	 *            the application context
	 * @return the singleton
	 */
	public static TimerConfigurationDao getInstance(Context context) {
		if (instance == null) {
			instance = new TimerConfigurationDao(context);
		}
		return instance;
	}

	/**
	 * Return all existing timer configuration.
	 * 
	 * @return the TimerConfiguration list
	 */
	public List<TimerConfiguration> getTimerConfigurations() {

		String sql = "SELECT " + TimerConfiguration.DbField.ID + "," + TimerConfiguration.DbField.NAME + "," + TimerConfiguration.DbField.TIMER_TYPE + ","
				+ TimerConfiguration.DbField.DURATION + "," + TimerConfiguration.DbField.HANDICAP + "," + TimerConfiguration.DbField.OWN_TUNE + ","
				+ TimerConfiguration.DbField.BEFORE_WARN + "," + TimerConfiguration.DbField.EVERY_WARN + "," + TimerConfiguration.DbField.OWN_TUNE_WARN + ","
				+ TimerConfiguration.DbField.LIMIT_REPORT + " from TIMER_CONFIGURATION order by " + TimerConfiguration.DbField.NAME + " asc";
		Cursor cursor = getDatabase().rawQuery(sql, new String[] {});
		ArrayList<TimerConfiguration> result = new ArrayList<TimerConfiguration>();
		if (cursor.moveToFirst()) {
			do {
				TimerConfiguration entity = new TimerConfiguration(cursor.getString(0));
				entity.setName(cursor.getString(1));
				entity.setTimerType(TimerType.values()[cursor.getInt(2)]);
				entity.setDuration(Integer.parseInt(cursor.getString(3)));
				entity.setHandicap(Integer.parseInt(cursor.getString(4)) != 0);
				entity.setOwnTune(cursor.getString(5));
				entity.setBeforeWarning(Integer.parseInt(cursor.getString(6)));
				entity.setEveryWarning(Integer.parseInt(cursor.getString(7)));
				entity.setOwnTuneWarning(cursor.getString(8));
				entity.setReportLimit(Integer.parseInt(cursor.getString(9)));
				result.add(entity);
			} while (cursor.moveToNext());
		}
		cursor.close();
		return result;
	}

	/**
	 * Persist a new TimerConfiguration.
	 * 
	 * @param timer
	 *            the new TimerConfiguration
	 */
	public void create(TimerConfiguration timer) {
		getDatabase().beginTransaction();
		try {
			String sql = "insert into TIMER_CONFIGURATION (" + TimerConfiguration.DbField.ID + "," + TimerConfiguration.DbField.NAME + "," + TimerConfiguration.DbField.TIMER_TYPE
					+ "," + TimerConfiguration.DbField.DURATION + "," + TimerConfiguration.DbField.HANDICAP + "," + TimerConfiguration.DbField.OWN_TUNE + ","
					+ TimerConfiguration.DbField.BEFORE_WARN + "," + TimerConfiguration.DbField.EVERY_WARN + "," + TimerConfiguration.DbField.OWN_TUNE_WARN + ","
					+ TimerConfiguration.DbField.LIMIT_REPORT + ") values (?,?,?,?,?,?,?,?,?,?)";
			Object[] params = new Object[10];
			params[0] = timer.getId();
			params[1] = timer.getName();
			params[2] = timer.getTimerType().ordinal();
			params[3] = timer.getDuration();
			params[4] = timer.isHandicap() ? 1 : 0;
			params[5] = timer.getOwnTune();
			params[6] = timer.getBeforeWarning();
			params[7] = timer.getEveryWarning();
			params[8] = timer.getOwnTuneWarning();
			params[9] = timer.getReportLimit();
			execSQL(sql, params);

			for (Player player : timer.getPlayers()) {
				player.setTimerConfigurationId(timer.getId());
				PlayerDao.getInstance(getContext()).create(player);
			}

			getDatabase().setTransactionSuccessful();
		} finally {
			getDatabase().endTransaction();
		}
	}

	/**
	 * Update an existing TimerConfiguration.
	 * 
	 * @param timer
	 *            the TimerConfiguration to update
	 */
	public void update(TimerConfiguration timer) {
		getDatabase().beginTransaction();
		try {
			String sql = "update TIMER_CONFIGURATION set " + TimerConfiguration.DbField.NAME + "=?," + TimerConfiguration.DbField.TIMER_TYPE + "=?,"
					+ TimerConfiguration.DbField.DURATION + "=?," + TimerConfiguration.DbField.HANDICAP + "=?," + TimerConfiguration.DbField.OWN_TUNE + "=?,"
					+ TimerConfiguration.DbField.BEFORE_WARN + "=?," + TimerConfiguration.DbField.EVERY_WARN + "=?," + TimerConfiguration.DbField.OWN_TUNE_WARN + "=?,"
					+ TimerConfiguration.DbField.LIMIT_REPORT + "=? WHERE " + TimerConfiguration.DbField.ID + "=?";
			Object[] params = new Object[10];
			params[0] = timer.getName();
			params[1] = timer.getTimerType().ordinal();
			params[2] = timer.getDuration();
			params[3] = timer.isHandicap() ? 1 : 0;
			params[4] = timer.getOwnTune();
			params[5] = timer.getBeforeWarning();
			params[6] = timer.getEveryWarning();
			params[7] = timer.getOwnTuneWarning();
			params[8] = timer.getReportLimit();
			params[9] = timer.getId();

			execSQL(sql, params);

			sql = "delete from PLAYER where " + Player.DbField.FK_CONFIGURATION + "=?";
			execSQL(sql, new String[] { timer.getId() });

			for (Player player : timer.getPlayers()) {
				player.setTimerConfigurationId(timer.getId());
				PlayerDao.getInstance(getContext()).create(player);
			}

			getDatabase().setTransactionSuccessful();
		} finally {
			getDatabase().endTransaction();
		}
	}

	public void delete(TimerConfiguration timer) {
		getDatabase().beginTransaction();
		try {
			String sql = "delete from PLAYER where " + Player.DbField.FK_CONFIGURATION + "=?";
			execSQL(sql, new String[] { timer.getId() });

			sql = "delete from TIMER_CONFIGURATION where " + TimerConfiguration.DbField.ID + "=?";
			execSQL(sql, new String[] { timer.getId() });

			getDatabase().setTransactionSuccessful();
		} finally {
			getDatabase().endTransaction();
		}

	}

	public void persist(TimerConfiguration timer) {
		if (timer.getState() == DbState.NEW) {
			create(timer);
		} else if (timer.getState() == DbState.LOADED) {
			update(timer);
		}
	}

}
